package com.zoro.dyformservice.support.web;

import com.zoro.dyformservice.interfaces.CodeData;
import com.zoro.dyformservice.support.response.CommonResponseBodyAdvice;
import com.zoro.dyformservice.support.response.CommonResponseFormat;
import com.zoro.dyformservice.support.web.converter.CodeDataFormatter;
import com.zoro.dyformservice.support.web.converter.CustomJsonSerializerProvider;
import com.zoro.dyformservice.utils.CollectionUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.format.FormatterRegistry;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice;

import java.util.Set;

public class WebConfig implements WebMvcConfigurer {

    private final Logger logger = LoggerFactory.getLogger(getClass());
    private final CustomJsonSerializerProvider provider;

    public WebConfig(CustomJsonSerializerProvider provider) {
        this.provider = provider;
    }

    @Bean
    public ResponseBodyAdvice<Object> responseBodyAdvice() {
        return new DefaultControllerAdvice();
    }

    @RestControllerAdvice(annotations = CommonResponseFormat.class)
    private class DefaultControllerAdvice extends CommonResponseBodyAdvice {
        public DefaultControllerAdvice() {
            logger.info("使用默认响应值包装器：{}", CommonResponseBodyAdvice.class);
        }
    }

    @SuppressWarnings("unchecked")
    @Override
    public void addFormatters(FormatterRegistry registry) {
        Set<Class<CodeData>> codeDataClass = provider.codeDataType();
        if (CollectionUtils.isEmpty(codeDataClass)) {
            logger.warn("There is no CodeData type.");
            return;
        }

        for (Class<? extends CodeData> c : codeDataClass) {
            logger.debug("register formatter {} for {}", "CodeDataFormatter", c);
            registry.addFormatterForFieldType(c, new CodeDataFormatter<>(c));
        }
    }
}
